package com.juicygames.framework.gamepart;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import android.util.Log;

import com.juicygames.framework.GameAction;
import com.juicygames.framework.exception.GameActionNotHandled;
import com.juicygames.framework.exception.GamePartNotFound;

public abstract class GamePart {
	private static final String LOGTAG = GamePart.class.getName();
	
	protected GamePart parent = null;
	private SubPartComponent subParts = null;
	private HandlersComponent handlers = null;
	
	public GamePart(GamePart parent) {
		this.parent = parent;
	}
	
	public GamePart getWorld() {
		if (parent == null) {
			return this;
		} else {
			return parent.getWorld();
		}
	}
	
	public void load() {}
	
	public <G extends GamePart> G addPart(G part) {
		if (subParts == null) {
			subParts = new SubPartComponent(this);
		}
		
		return subParts.addPart(part);
	}
	
	public <PartTypeParam extends GamePart> PartTypeParam getPart(Class<PartTypeParam> partClass) {
		if (subParts == null) {
			throw new GamePartNotFound(this.toString() + " has no sub parts to find " + partClass.toString());
		}
		
		return subParts.getPart(partClass);
	}
	
	public <G extends GamePart>boolean containsPart(GamePart part) {
		if (subParts == null) {
			return false;
		}
		
		return subParts.containsPart(part);
	}
	
	public <G extends GamePart> List<G> getParts(Class<G> partClass) {
		if (subParts == null) {
			return new ArrayList<G>();
		}
		
		return subParts.getParts(partClass);
	}
	
	public <HandlerTypeParam extends GameHandler> HandlerTypeParam addHandler(HandlerTypeParam handler) {
		if (handlers == null) {
			handlers = new HandlersComponent(this);
		}
		
		return handlers.addHandler(handler);
	}
	
	public void handleAction(GameAction action) throws GameActionNotHandled {
		if (handlers == null) {
			throw new GameActionNotHandled(this.toString() + " has no handlers to handle " + action.toString());
		}
		
		handlers.handleAction(action);
	}
	
	public boolean tryToHandleAction(GameAction action) {
		if (handlers == null) {
			return false;
		}
		
		return handlers.tryToHandleAction(action);
	}
	
	public void groundHandler(GameHandler handler) {
		if (parent != null) {
			ActionForwarder forwarderHandler = new ActionForwarder(parent, this, handler.getActionClassHandled());
			if (!parent.containsPart(forwarderHandler)) {
				parent.addHandler(forwarderHandler);
				parent.groundHandler(forwarderHandler);
			}
		}
	}

}
